tg-me.com/sqlhub/1875
Last Update:
🛢️ SQL-задача с подвохом: GROUP BY и скрытая ловушка
Условие:
Есть таблица orders
:
| id | customer_id | amount | status |
|-----|-------------|--------|-----------|
| 1 | 101 | 200 | completed |
| 2 | 102 | 150 | NULL |
| 3 | 101 | 300 | completed |
| 4 | 103 | NULL | completed |
| 5 | 102 | 100 | completed |
| 6 | 101 | 250 | NULL |
Задача: найти всех клиентов, у которых сумма заказов больше 500.
Ты пишешь запрос:
SELECT customer_id, SUM(amount) as total
FROM orders
GROUP BY customer_id
HAVING SUM(amount) > 500;
❓ Вопрос:
Какие клиенты вернутся? Есть ли тут подвох? Что произойдёт с заказами, где
amount
или status
— NULL
?🔍 Подвох:
На первый взгляд запрос правильный: мы группируем по клиентам и суммируем их заказы. Но вот критичные моменты:
1️⃣ Что происходит с NULL в `amount`?
В SQL агрегатные функции (например, SUM) игнорируют NULL значения. Это значит:
- Заказ id=4 (`amount = NULL`) не участвует в суммировании.
- Заказ id=6 (`amount = 250`) участвует, потому что amount не NULL.
2️⃣ Считаем по каждому клиенту:
- customer_id=101:
- id=1: 200
- id=3: 300
- id=6: 250
Итого: 200 + 300 + 250 = 750
- customer_id=102:
- id=2: 150
- id=5: 100
Итого: 150 + 100 = 250
- customer_id=103:
- id=4: NULL (игнорируется)
Итого: 0
3️⃣ Кто попадёт в результат:
Только customer_id=101 (с суммой 750 > 500).
---
✅ Результат:
| customer_id | total |
|-------------|--------|
| 101 | 750 |
---
💥 Подвох #2:
Допустим ты случайно написал:
HAVING SUM(amount) IS NOT NULL AND SUM(amount) > 500;
Кажется логичным? А вот нет: SUM всегда возвращает 0 (не NULL), даже если у клиента нет заказов с ненулевой суммой.
➡️ Даже клиент с только NULL значениями (например, customer_id=103) получит SUM(amount) = 0, а не NULL.
Это частая ловушка:
COUNT, SUM, AVG игнорируют NULL внутри, но результат НЕ NULL (обычно 0 или NULL в зависимости от агрегата).
---
🛠 Что ещё важно:
• Если хочешь учитывать только выполненные заказы (status = 'completed'), нужно добавить:
WHERE status = 'completed'
⚠️ Не пиши условие в HAVING для фильтрации строк — лучше фильтровать через WHERE до группировки.
✅ Вывод:
- ✅ Агрегатные функции типа SUM игнорируют NULL внутри группы.
- ✅ SUM возвращает 0, даже если все значения NULL (НЕ NULL, как думают многие).
- ✅ HAVING применяется ПОСЛЕ группировки, а WHERE — ДО.
- ✅ Ошибки часто возникают, если условие на фильтр пишут в HAVING вместо WHERE.
💡 Бонус-вопрос:
Что будет, если заменить
SUM(amount)
на COUNT(amount)
в SELECT и HAVING? И как это повлияет на клиентов с NULL значениями?@sqlhub
BY Data Science. SQL hub
Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283
Share with your friend now:
tg-me.com/sqlhub/1875